﻿#include <QFileDialog>
#include <QMessageBox>  
#include <QDebug>
#include <QDesktopWidget>  
#include <QRect>

#include "pclviewer.h"
#include "ui_pclviewer.h"

#define ROTATE_IS_INIT      0
#define ROTATE_IS_ROTATE    1
#define ROTATE_IS_STOP      2

#define DEFAULT_ROTATE_SPPED   2048

PCLViewer::PCLViewer (QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::PCLViewer)
{
    ui->setupUi(this);
	this->setWindowTitle(QStringLiteral("点云数据采集系统"));
	
    m_cloud = new pclCloud();
    m_mutex = new myMutex();
	m_Rmutex = new myMutex();
	m_samp = new QSemaphore(0);//已用量  

    m_pTimer = new QTimer(this);
    m_angle = 0;
	m_speed = 1;

    showPicture();
    initWidget();

    // Set up the QVTK window
    viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));
    ui->qvtkWidget->SetRenderWindow(viewer->getRenderWindow());
    viewer->setupInteractor(ui->qvtkWidget->GetInteractor(), ui->qvtkWidget->GetRenderWindow());
    ui->qvtkWidget->update();

    m_serialPort = NULL;
    initdefault();

    connectRegsit();

    viewer->addPointCloud(cloud, "cloud");
    pSliderValueChanged(2);
    viewer->resetCamera();
    //viewer->addCoordinateSystem (1);
    //viewer->setBackgroundColor(1.0, 0.5, 1.0);
    ui->qvtkWidget->update();

	QDesktopWidget* pDesktopWidget = QApplication::desktop();
	m_deskRect = pDesktopWidget->availableGeometry();

	setWindowState(Qt::WindowMaximized);

	int grpWidth  = ui->groupBox->width();
	int grpHeight = ui->groupBox->height();

	int vtkWidth  = ui->qvtkWidget->width();
	int vtkHeight = ui->qvtkWidget->height();

	int logWidth  = ui->mainPictureBox->width();
	int logHeight = ui->mainPictureBox->height();

	vtkWidth  = m_deskRect.width() - grpWidth - 20 + 20 + 20 - 50;
	vtkHeight = m_deskRect.height() - grpHeight - 20 - 20 - logHeight - 60;
	ui->qvtkWidget->setMinimumSize(vtkWidth, vtkHeight);

	initPort();
}

PCLViewer::~PCLViewer()
{
    delete ui;
}

void PCLViewer::initWidget()
{
    //ui->lcdNumber_R->setVisible(false);
    //ui->lcdNumber_G->setVisible(false);
    //ui->lcdNumber_B->setVisible(false);
    //ui->lcdNumber_p->setVisible(false);
    //ui->lcdNumberL_Label_R->setVisible(false);
    //ui->lcdNumberL_Label_B->setVisible(false);
    //ui->lcdNumberL_Label_G->setVisible(false);
    //ui->lcdNumberL_Label_p->setVisible(false);
    //ui->horizontalSlider_R->setVisible(false);
    //ui->horizontalSlider_G->setVisible(false);
    //ui->horizontalSlider_B->setVisible(false);
    //ui->horizontalSlider_p->setVisible(false);

    m_bg = new QButtonGroup(this);
    m_bg->addButton(ui->comRadioBtn, 0);//一个值为0
    m_bg->addButton(ui->usbRadioBtn, 1);//一个值为1
    ui->comRadioBtn->setChecked(true);  // 为operatingModeGroup组设置初选项
    setComStatus(false);
    setUsbStatus(false);
    updateRadioBtnStatus();

	setRotateStatus(ROTATE_IS_INIT);
}

void PCLViewer::updateRadioBtnStatus()
{
    int sel = m_bg->checkedId();//取到你所选的radioButton的值
    switch (sel)
    {
        case 0:
        {
            QString comStr;
            if (!isComOn())
            {
                comStr = QStringLiteral("启动串口传输");
            }
            else
            {
                comStr = QStringLiteral("停止串口传输");
            }
            ui->datTransmitTypeBtn->setText(comStr);
            break;
        }
        case 1:
        {
            QString usbStr;
            if (!isUsbOn())
            {
                usbStr = QStringLiteral("启动USB传输");
            }
            else
            {

                usbStr = QStringLiteral("停止USB传输");
            }
            ui->datTransmitTypeBtn->setText(usbStr);
            break;
        }
        default:
            break;
    }
}

void PCLViewer::onRadioClickEvent()
{
    int sel = m_bg->checkedId();//取到你所选的radioButton的值
    switch (sel)
    {
        case 0:
        {
            closeUsbPort();
            QString comStr;
            if (!isComOn())
            {
                comStr = QStringLiteral("启动串口传输");
            }
            else
            {
                comStr = QStringLiteral("停止串口传输");
            }
            ui->datTransmitTypeBtn->setText(comStr);
            break;
        }
        case 1:
        {
            closeComPort();
            QString usbStr;
            if (!isUsbOn())
            {
                usbStr = QStringLiteral("启动USB传输");
            }
            else
            {

                usbStr = QStringLiteral("停止USB传输");
            }
            ui->datTransmitTypeBtn->setText(usbStr);
            break;
        }
        default:
                break;
    }
}

void PCLViewer::initdefault()
{
    // Setup the cloud pointer
    cloud.reset(new PointCloudT);
    // The number of points in the cloud
    cloud->points.resize(200);
    // The default color
    red = 128;
    green = 128;
    blue = 128;

    // Fill the cloud with some points
    for (size_t i = 0; i < cloud->points.size(); ++i)
    {
        cloud->points[i].x = 1 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].y = 1 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].z = 1 * rand() / (RAND_MAX + 1.0f);

        cloud->points[i].r = red;
        cloud->points[i].g = green;
        cloud->points[i].b = blue;
    }
}

void PCLViewer::connectRegsit()
{
    // Connect "random" button and the function
    connect(ui->pushButton_random, SIGNAL(clicked()), this, SLOT(randomButtonPressed()));
    connect(ui->pushButton_open, SIGNAL(clicked()), this, SLOT(openPcdButtonPressed()));
    connect(ui->pushButton_rotate, SIGNAL(clicked()), this, SLOT(rotateButtonPressed()));
    connect(ui->pushButton_saveFile, SIGNAL(clicked()), this, SLOT(saveFileButtonPressed()));

    // Connect R,G,B sliders and their functions
    connect(ui->horizontalSlider_R, SIGNAL(valueChanged(int)), this, SLOT(redSliderValueChanged(int)));
    connect(ui->horizontalSlider_G, SIGNAL(valueChanged(int)), this, SLOT(greenSliderValueChanged(int)));
    connect(ui->horizontalSlider_B, SIGNAL(valueChanged(int)), this, SLOT(blueSliderValueChanged(int)));
    connect(ui->horizontalSlider_R, SIGNAL(sliderReleased()), this, SLOT(RGBsliderReleased()));
    connect(ui->horizontalSlider_G, SIGNAL(sliderReleased()), this, SLOT(RGBsliderReleased()));
    connect(ui->horizontalSlider_B, SIGNAL(sliderReleased()), this, SLOT(RGBsliderReleased()));

	connect(ui->horizontalSlider_Speed, SIGNAL(valueChanged(int)), this, SLOT(SpeedSliderValueChanged(int)));

    // Connect point size slider
    connect(ui->horizontalSlider_p, SIGNAL(valueChanged(int)), this, SLOT(pSliderValueChanged(int)));

    connect(ui->comRadioBtn, SIGNAL(clicked()), this, SLOT(onRadioClickEvent()));
    connect(ui->usbRadioBtn, SIGNAL(clicked()), this, SLOT(onRadioClickEvent()));
    connect(ui->datTransmitTypeBtn, SIGNAL(clicked()), this, SLOT(onComTransmiBtnDwnEvent()));

    connect(m_pTimer, SIGNAL(timeout()), this, SLOT(onTimer()));
}

void PCLViewer::showPicture()
{
#if 1
	int width, height;
	width = ui->mainPictureBox->width();
	height = ui->mainPictureBox->height();
    QPixmap  image; //定义一张图片
    //image.load("E:\\codc\\pclCodec\\iShow\\src\\show.jpg");//加载
    image.load(".\\resource\\mainLog.jpg");//加载
	image = image.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//设置图片大小和label的长宽一致
	ui->mainPictureBox->clear();//清空
	ui->mainPictureBox->setPixmap(image);//加载到Label标签
	ui->mainPictureBox->show();//显示

	width = ui->subPictureBox->width();
	height = ui->subPictureBox->height();
    //image.load("E:\\codc\\pclCodec\\iShow\\src\\show.jpg");//加载
    image.load(".\\resource\\subLog.jpg");//加载
	image = image.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//设置图片大小和label的长宽一致
	ui->subPictureBox->clear();//清空
	ui->subPictureBox->setPixmap(image);//加载到Label标签
	ui->subPictureBox->show();//显示
#else
	int width, height;
	width = ui->mainPictureBox->width();
	height = ui->mainPictureBox->height();
	QImage* imgSource = new QImage(QString(".\\mainLog.jpg"));
	QImage* imgScaled = new QImage();
	*imgScaled = imgSource->scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//设置图片大小和label的长宽一致
	ui->mainPictureBox->setPixmap(QPixmap::fromImage(*imgScaled));

	width = ui->mainPictureBox->width();
	height = ui->mainPictureBox->height();
	imgSource = new QImage(QString(".\\subLog.jpg"));
	imgScaled = new QImage();
	*imgScaled = imgSource->scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//设置图片大小和label的长宽一致
	ui->subPictureBox->setPixmap(QPixmap::fromImage(*imgScaled));
#endif

	QPalette pal(this->palette());
	pal.setColor(QPalette::Background, Qt::white); //设置背景黑色
	this->setAutoFillBackground(true);
	this->setPalette(pal);

	ui->datTransmitTypeBtn->setStyleSheet("background-color: rgb(18,43,107); color: rgb(255,255,255);"); //rgb(170, 0, 255); ");
	ui->pushButton_random->setStyleSheet("background-color: rgb(18,43,107); color: rgb(255,255,255);"); //rgb(170, 0, 255); ");
	ui->pushButton_rotate->setStyleSheet("background-color: rgb(18,43,107); ; color: rgb(255,255,255);");
	ui->pushButton_open->setStyleSheet("background-color: rgb(18,43,107); ; color: rgb(255,255,255);");
	ui->pushButton_saveFile->setStyleSheet("background-color: rgb(18,43,107); ; color: rgb(255,255,255);");

	QFont font("宋体", 18, 50);
	ui->datTransmitTypeBtn->setFont(font);
	ui->pushButton_random->setFont(font);
	ui->pushButton_rotate->setFont(font);
	ui->pushButton_open->setFont(font);
	ui->pushButton_saveFile->setFont(font);
}

void PCLViewer::onComTransmiBtnDwnEvent()
{
    int sel = m_bg->checkedId();//取到你所选的radioButton的值
    switch (sel)
    {
        case 0:
        {
            if (isUsbOn())
            {
                closeUsbPort();
            }
            if (!isComOn())
            {
                openComPort("com1", 9600);
                //QObject::connect(m_serialPort, &QSerialPort::readyRead, this, &PCLViewer::onEventRecv);
                connect(m_serialPort, SIGNAL(readyRead()), this, SLOT(onEventRecv()));
            }
            else
            {
                closeComPort();
            }            
            break;
        }
        case 1:
        {
            if (isComOn())
            {
                closeComPort();
            }
            if (!isUsbOn())
            {
                openUsbPort();;
                //connect(...);
            }
            else
            {
                closeUsbPort();
            }
            break;
        }
        default:
            break;
    }
}

//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
void PCLViewer::onTimer()
{
	m_samp->release();//空闲信号量加1  
    //qDebug() << "Enter timeout processing function\n";
    m_mutex->lock();
    viewer->updatePointCloud(cloud, "cloud");
    m_mutex->unlock();
    viewer->resetCamera ();
    ui->qvtkWidget->update();


}

void PCLViewer::rotateButtonPressed ()
{
    printf("rotate button was pressed\n");

	if (ROTATE_IS_INIT == getRotateStatus())
	{
		m_myThread.regist(m_cloud, cloud, m_angle, m_mutex, m_Rmutex, m_samp);
		m_myThread.start();
		m_myThread.setStatus(true);
		m_pTimer->start(DEFAULT_ROTATE_SPPED >> m_speed);
		setRotateStatus(ROTATE_IS_ROTATE);
	}
	else if (ROTATE_IS_ROTATE == getRotateStatus())
	{
		m_mutex->lock();
		m_cloud->disable();
		m_mutex->unlock();
		setRotateStatus(ROTATE_IS_STOP);
	}
	else if (ROTATE_IS_STOP == getRotateStatus())
	{
		m_mutex->lock();
		m_cloud->enable();
		m_mutex->unlock();
		setRotateStatus(ROTATE_IS_ROTATE);
	}
}

void PCLViewer::openPcdButtonPressed ()
{
    printf ("open pcd button was pressed\n");

	if (ROTATE_IS_ROTATE == getRotateStatus())
	{
		if (m_myThread.isStart())
		{
			m_myThread.quit();
		}
		setRotateStatus(ROTATE_IS_INIT);
	}

    QString fileName = QFileDialog::getOpenFileName(  
                    this, tr("open image file"),  
                    "./", tr("Txt files(*.txt )"));  

    if(fileName.isEmpty())  
    {  
        QMessageBox mesg;  
        mesg.warning(this,"璀﹀憡","鎵撳紑鏂囦欢澶辫触!");  
        return;  
    }  
    else  
    {
        QString displayString;
        m_mutex->lock();
        cloud = m_cloud->loadFile(fileName);
        m_mutex->unlock();

        // for the time, this value will be add 2 once.
        if (0 == cloud->width)
        {
            // in this sutiation, means inputing a empty txt pcd file, skip the following process.
        }
        else
        {
            cloud->width--;

            cloud->height = 1;
            cloud->is_dense = false;
            cloud->points.resize(cloud->height*cloud->width);

            m_mutex->lock();
            m_cloud->normalize(cloud);
            m_mutex->unlock();

            //viewer->removeAllPointClouds();
            viewer->updatePointCloud(cloud, "cloud");
            viewer->resetCamera();
            ui->qvtkWidget->update();
        }
    }  
}

void PCLViewer::saveFileButtonPressed()
{
    printf("Save file button was pressed\n");

    QString fileName = QFileDialog::getSaveFileName(
        this, tr("open file file"),
        "./", tr("Txt files(*.txt )"));

    if (fileName.isEmpty())
    {
        QMessageBox mesg;
        mesg.warning(this, "fail to open file", " ");
        return;
    }
    else
    {
        QString displayString;
        m_mutex->lock();
        m_cloud->saveFile(fileName);
        m_mutex->unlock();
    }
}

void PCLViewer::randomButtonPressed()
{
    printf("Random button was pressed\n");

    // Set the new color
    for (size_t i = 0; i < cloud->size(); i++)
    {
        cloud->points[i].r = 255 * (1024 * rand() / (RAND_MAX + 1.0f));
        cloud->points[i].g = 255 * (1024 * rand() / (RAND_MAX + 1.0f));
        cloud->points[i].b = 255 * (1024 * rand() / (RAND_MAX + 1.0f));
    }

    viewer->updatePointCloud(cloud, "cloud");
    ui->qvtkWidget->update();
}

void PCLViewer::RGBsliderReleased ()
{
  // Set the new color
  for (size_t i = 0; i < cloud->size (); i++)
  {
    cloud->points[i].r = red;
    cloud->points[i].g = green;
    cloud->points[i].b = blue;
  }
  viewer->updatePointCloud (cloud, "cloud");
  ui->qvtkWidget->update ();
}

void PCLViewer::pSliderValueChanged (int value)
{
  viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, value, "cloud");
  ui->qvtkWidget->update ();
}

void PCLViewer::redSliderValueChanged (int value)
{
  red = value;
  printf ("redSliderValueChanged: [%d|%d|%d]\n", red, green, blue);
}

void PCLViewer::greenSliderValueChanged (int value)
{
  green = value;
  printf ("greenSliderValueChanged: [%d|%d|%d]\n", red, green, blue);
}

void PCLViewer::blueSliderValueChanged (int value)
{
  blue = value;
  printf("blueSliderValueChanged: [%d|%d|%d]\n", red, green, blue);
}

void PCLViewer::SpeedSliderValueChanged(int value)
{
	m_speed = value;
	if (m_speed == 0)
	{
		m_pTimer->stop();
		printf("SpeedSliderValueChanged: [%d]\n", m_speed);
	}
	else if ((0 == m_lastSpeed) && (0 != m_speed))
	{
		m_pTimer->start(DEFAULT_ROTATE_SPPED >> m_speed);
	}
	else
	{
		m_pTimer->setInterval(DEFAULT_ROTATE_SPPED >> m_speed);
		printf("SpeedSliderValueChanged: [%d]\n", m_speed);
	}
	m_lastSpeed = m_speed;
}

void PCLViewer::SpeedBsliderReleased()
{
	ui->qvtkWidget->update();
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// serial port process
void PCLViewer::initPort()
{
	m_serialPort = new QSerialPort();
	m_Drv = new usbDrv();
}

void PCLViewer::openComPort(char *comName, int iBaudRate)
{
    m_serialPort->setPortName(comName);               //设置串口名  
    m_serialPort->open(QIODevice::ReadWrite);         //打开串口
    m_serialPort->setBaudRate(iBaudRate);             //设置波特率  
    m_serialPort->setDataBits(QSerialPort::Data8);    //设置数据位数
    m_serialPort->setParity(QSerialPort::NoParity);   //设置奇偶校验
    m_serialPort->setStopBits(QSerialPort::OneStop);  //设置停止位
    m_serialPort->setFlowControl(QSerialPort::NoFlowControl); //设置流控制
    m_currentPortName = comName;
    setComStatus(true);
    QString comStr = QStringLiteral("停止串口传输");
    ui->datTransmitTypeBtn->setText(comStr);
}

void PCLViewer::closeComPort()
{
    if (NULL != m_serialPort)
    {
        m_serialPort->close();
    }
    setComStatus(false);
    QString comStr = QStringLiteral("启动串口传输");
    ui->datTransmitTypeBtn->setText(comStr);

}

void PCLViewer::openUsbPort()
{
	m_Vid = 0x048D;
	m_Pid = 0x1234;
	m_Drv->usbOpen(m_Vid, m_Pid);
    setUsbStatus(true);
    QString usbStr = QStringLiteral("停止USB传输");

	m_usbThread.regist(m_Rmutex, m_samp, m_Drv, (char*)m_RBuffer);
	m_Drv->usbSend((char*)m_RBuffer, 64, UNBLOCK);
	m_usbThread.start();
	m_usbThread.setStatus(true);

    ui->datTransmitTypeBtn->setText(usbStr);
}

void PCLViewer::closeUsbPort()
{
	m_usbThread.quit();
	m_Drv->usbClose();
	setUsbStatus(false);
    QString usbStr = QStringLiteral("启动USB传输");
    ui->datTransmitTypeBtn->setText(usbStr);
}

void PCLViewer::sendData()
{
    QString sendMsg = "12345"; //serialPortAssitant.sendLine->text();
    QByteArray temp = sendMsg.toLatin1();
#if 0
    if (IsSendByHex)
    {
        temp = HexStrToByteArray(sendMsg);
    }
#endif
    char *sendContent = temp.data();
    qint64 sendedNum = m_serialPort->write(sendContent, temp.count());

    //---------------判断发送数据是否成功----------------------//  
    if (sendedNum == -1)
    {
        m_err = m_serialPort->error();

        QString errorInfo = " ";
        errorInfo = QString::fromLocal8Bit("错误提示信息: ");
        errorInfo += "\n";
        //serialPortAssitant.ReciveWidget->append(errorInfo + getValueContent(errorValue));
        return;
    }
}

void PCLViewer::recvData()
{
    if (m_serialPort->bytesAvailable() < 0)
    {
        //serialPortAssitant.ReciveWidget->setText("No data");
        return;
    }

    QByteArray recvData = m_serialPort->readAll();

    QString receiveMsg;
    if (m_isReceiveByHex)
    {
        //receiveMsg = ByteArrayToHexStr(recvData);
    }
    else
    {
        receiveMsg = recvData;
    }
    if (receiveMsg.isEmpty())
    {
        //serialPortAssitant.ReciveWidget->append(errorInfo + QString::fromLocal8Bit("没有读到数据\n"));
        return;
    }
    //接收到的字节数以初始的bytes为依据
    QString showReciveMsg;
    showReciveMsg = QString::fromLocal8Bit("接收数据 : ");
    showReciveMsg += receiveMsg;
    //serialPortAssitant.ReciveWidget->append(showReciveMsg);
}

void PCLViewer::onSerialReady()
{
    m_serialPort->readyRead();
}

void PCLViewer::onEventRecv()
{
    recvData();
}


void PCLViewer::setComStatus(bool devStatus)
{
    m_isComOn = devStatus;
}

bool PCLViewer::isComOn()
{
    return m_isComOn;
}

void PCLViewer::setUsbStatus(bool devStatus)
{
    m_isUsbOn = devStatus;
}

bool PCLViewer::isUsbOn()
{
    return m_isUsbOn;
}

void PCLViewer::setRotateStatus(int status)
{
	if (ROTATE_IS_INIT == status)
	{
		QString posStr = QStringLiteral("启动点云刷新");
		ui->pushButton_rotate->setText(posStr);
	}
	else if (ROTATE_IS_ROTATE == status)
	{
		QString posStr = QStringLiteral("停止点云刷新");
		ui->pushButton_rotate->setText(posStr);
	}
	else if (ROTATE_IS_STOP == status)
	{
		QString posStr = QStringLiteral("恢复点云刷新");
		ui->pushButton_rotate->setText(posStr);
	}
	m_rotateStatus = status;
}

int PCLViewer::getRotateStatus()
{
	return m_rotateStatus;
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------

//--------------------------------------------------------------------
//--------------------------------------------------------------------
//USB Driver

//--------------------------------------------------------------------
//--------------------------------------------------------------------
